package com.ljf.config.domain.service;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ljf.common.domain.service.BasisDomainService;
import com.ljf.common.exception.ServiceException;
import com.ljf.common.utils.CollectionUtil;
import com.ljf.common.utils.EnumUtil;
import com.ljf.config.domain.base.ConfigBaseImpulseSenderHeaderBaseService;
import com.ljf.config.domain.repository.ConfigBaseImpulseSenderDetailRepository;
import com.ljf.config.domain.repository.ConfigBaseImpulseSenderHeaderRepository;
import com.ljf.config.domain.repository.ConfigDatImpulseSenderConditionRepository;
import com.ljf.config.dto.command.ConfigBaseImpulseSenderDetailCommand;
import com.ljf.config.dto.command.ConfigBaseImpulseSenderHeaderCommand;
import com.ljf.config.dto.command.ConfigDatImpulseSenderConditionCommand;
import com.ljf.config.dto.query.ConfigBaseImpulseSenderDetailQuery;
import com.ljf.config.dto.query.ConfigBaseImpulseSenderHeaderQuery;
import com.ljf.config.dto.query.ConfigDatImpulseSenderConditionQuery;
import com.ljf.config.enums.ConfigBaseImpulseSenderDetailTypeDateFormatEnum;
import com.ljf.config.enums.ConfigBaseImpulseSenderDetailTypeEnum;
import com.ljf.config.enums.ConfigBaseImpulseSenderHeaderBelongServiceEnum;
import com.ljf.config.model.ConfigBaseImpulseSenderDetail;
import com.ljf.config.model.ConfigBaseImpulseSenderHeader;
import com.ljf.config.model.ConfigDatImpulseSenderCondition;
import com.ljf.config.vo.ConfigBaseImpulseSenderDetailVO;
import com.ljf.config.vo.ConfigBaseImpulseSenderHeaderVO;
import com.ljf.config.vo.ConfigDatImpulseSenderConditionVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 发号器配置表头  领域服务
 *
 * @author LJF
 * @since 2025-01-09
 */
@Component
@AllArgsConstructor
public class ConfigBaseImpulseSenderHeaderDomainService extends BasisDomainService<ConfigBaseImpulseSenderHeaderRepository, ConfigBaseImpulseSenderHeaderQuery, ConfigBaseImpulseSenderHeaderVO, ConfigBaseImpulseSenderHeader, ConfigBaseImpulseSenderHeaderCommand> {

    private final ConfigBaseImpulseSenderHeaderBaseService baseService;
    private final ConfigBaseImpulseSenderDetailRepository detailRepository;
    private final ConfigDatImpulseSenderConditionRepository conditionRepository;

    @Override
    public ConfigBaseImpulseSenderHeader add(ConfigBaseImpulseSenderHeaderCommand command) throws ServiceException {
        ConfigBaseImpulseSenderHeaderBelongServiceEnum belongServiceEnum = EnumUtil.getEnumByCode(
                command.getBelongServiceCode(), ConfigBaseImpulseSenderHeaderBelongServiceEnum.values()
        );
        if (belongServiceEnum == null) {
            throw new ServiceException("新增操作失败: 归属服务不存在");
        }
        command.setBelongService(belongServiceEnum.getDbCode());
        ConfigBaseImpulseSenderHeader model = super.add(command);
        List<ConfigBaseImpulseSenderDetail> detailList = new ArrayList<>();
        for (ConfigBaseImpulseSenderDetailCommand detailCommand : command.getDetailList()) {
            String value = detailCommand.getValue();
            if (Objects.equals(ConfigBaseImpulseSenderDetailTypeEnum.CURRENT_DATE.getCode(), detailCommand.getType())) {
                ConfigBaseImpulseSenderDetailTypeDateFormatEnum formatEnum = EnumUtil.getEnumByCode(Integer.parseInt(value), ConfigBaseImpulseSenderDetailTypeDateFormatEnum.values());
                if (formatEnum == null) {
                    throw new ServiceException("新增操作失败: 日期格式不存在");
                }
                value = formatEnum.getFormat();
            }
            detailList.add(
                    ConfigBaseImpulseSenderDetail.builder()
                            .code(command.getCode())
                            .sort(detailCommand.getSort())
                            .type(detailCommand.getType())
                            .value(value)
                            .build()
            );
        }
        detailRepository.insertBatch(detailList);
        return model;
    }

    @Override
    public Page<ConfigBaseImpulseSenderHeaderVO> query(ConfigBaseImpulseSenderHeaderQuery query) throws ServiceException {
        Page<ConfigBaseImpulseSenderHeaderVO> page = super.query(query);
        if (CollectionUtil.isNotEmpty(page.getRecords())) {
            List<String> codeList = page.getRecords().stream()
                    .map(ConfigBaseImpulseSenderHeaderVO::getCode).collect(Collectors.toList());
            List<String> uniqueCodeList = this.getUniqueCodeList(codeList, false);
            for (int i = 0; i < page.getRecords().size(); i++) {
                page.getRecords().get(i).setExampleCode(uniqueCodeList.get(i));
            }
        }
        return page;
    }

    /**
     * 生成编码
     *
     * @param codeList
     * @param generateFlag
     * @return
     * @throws ServiceException
     */
    public List<String> getUniqueCodeList(List<String> codeList, boolean generateFlag) throws ServiceException {
        if (CollectionUtil.isEmpty(codeList)) {
            return Collections.emptyList();
        }
        List<ConfigBaseImpulseSenderHeaderVO> headerList = repository.selectList(
                ConfigBaseImpulseSenderHeaderQuery.builder().codeList(codeList).build()
        );
        List<ConfigBaseImpulseSenderDetailVO> detailList = detailRepository.selectList(
                ConfigBaseImpulseSenderDetailQuery.builder().codeList(codeList).build()
        );
        List<ConfigDatImpulseSenderConditionVO> conditionList = conditionRepository.selectList(
                ConfigDatImpulseSenderConditionQuery.builder().codeList(codeList).build()
        );
        List<String> uniqueCodeList = baseService.generateUniqueCodeList(codeList, headerList, detailList, conditionList, generateFlag);
        if (generateFlag) {
            conditionList.sort(Comparator.comparing(ConfigDatImpulseSenderConditionVO::getCount));
            Map<Long, ConfigDatImpulseSenderCondition> updateBatchMap = new HashMap<>();
            for (ConfigDatImpulseSenderConditionVO condition : conditionList) {
                updateBatchMap.put(
                        condition.getId(),
                        ConfigDatImpulseSenderCondition.builder()
                                .id(condition.getId())
                                .currentValue(condition.getCurrentValue())
                                .recordDate(condition.getRecordDate())
                                .build()
                );
            }
            conditionRepository.updateBatchByIds(new ArrayList<>(updateBatchMap.values()));
        }
        return uniqueCodeList;
    }

    /**
     * 初始化发号器配置
     *
     * @param command
     * @return
     * @throws ServiceException
     */
    public boolean intiCondition(ConfigDatImpulseSenderConditionCommand command) throws ServiceException {
        List<ConfigBaseImpulseSenderDetailVO> detailList = detailRepository.selectList(
                ConfigBaseImpulseSenderDetailQuery.builder()
                        .code(command.getCode())
                        .type(ConfigBaseImpulseSenderDetailTypeEnum.SERIAL_NUMBER.getCode())
                        .build()
        );
        Date date = new Date();
        if (CollectionUtil.isEmpty(detailList)) {
            conditionRepository.insert(
                    ConfigDatImpulseSenderCondition.builder()
                            .code(command.getCode())
                            .sort(-1)
                            .currentValue("")
                            .recordDate(date)
                            .build()
            );
        }
        else {
            List<ConfigDatImpulseSenderCondition> needInsert = new ArrayList<>();
            for (ConfigBaseImpulseSenderDetailVO detail : detailList) {
                needInsert.add(
                        ConfigDatImpulseSenderCondition.builder()
                                .code(command.getCode())
                                .sort(detail.getSort())
                                .currentValue("0")
                                .recordDate(date)
                                .build()
                );
            }
            conditionRepository.insertBatch(needInsert);
        }
        return true;
    }

}
